
module OutputGenerator(
  input  wire        clk,
  input  wire        rst_n,
  input  wire        clken,
  input  wire [ 4:0] slot,
  input  wire [ 1:0] stage,
  input  wire        rhythm,
  input  wire [ 7:0] opout,
  input  wire [ 3:0] faddr,
  output wire [ 9:0] fdata,
  input  wire [ 4:0] maddr,
  output wire [ 9:0] mdata
);


reg       fb_wr;
reg [3:0] fb_addr;
reg [9:0] fb_wdata;
FeedbackMemory U_FeedbackMemory(
    .clk (clk),
    .rst_n (rst_n),
    .wr (fb_wr),
    .waddr(fb_addr),
    .wdata(fb_wdata),
    .raddr(faddr),
    .rdata(fdata)
);

reg        mo_wr;
reg  [4:0] mo_addr;
reg  [9:0] mo_wdata;
wire [9:0] mo_rdata;
OutputMemory U_OutputMemory(
    .clk (clk),
    .rst_n(rst_n),
    .wr (mo_wr),
    .addr(mo_addr),
    .wdata(mo_wdata),
    .rdata(mo_rdata),
    .addr2(maddr),
    .rdata2(mdata)
);

wire [9:0] li_data;
reg  [7:0] li_addr;
LinearTable U_LinearTable(
    .clk (clk),
    .rst_n (rst_n),
    .addr(li_addr),
    .data(li_data)
);

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	fb_wr <= #1 1'b0;
    else if(clken)
	fb_wr <= #1 fb_wr;
    else if(stage == 2'b0)
	fb_wr <= #1 1'b0;
    else if(stage == 2'd2)
	fb_wr <= #1 ~slot[0];
    else if(stage == 2'd3)
	fb_wr <= #1 1'b0;
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	 fb_addr <= #1 4'b0;
    else if(clken)
	 fb_addr <= #1 fb_addr;
    else if((stage == 2'd2) && (!slot[0]))
	 fb_addr <= #1 slot[4:1];
end

wire[10:0] vR = li_data[9] ? (~({2'b00, li_data[8:0]})) + 1'b1 : {2'b00, li_data[8:0]};
wire[10:0] vL_tmp = mo_rdata[9] ? (~({2'b00, mo_rdata[8:0]})) + 1'b1 : {2'b00, mo_rdata[8:0]};
wire[10:0] vL  = vL_tmp + vR;
wire[10:0] vL2 = ~(vL - 1'b1);
reg[9:0] fb_wdata_tmp;
always @(*)begin
    if(!vL[10])
	fb_wdata_tmp = {1'b0, vL[9:1]};
    else
	fb_wdata_tmp = {1'b1, vL2[9:1]};    
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	fb_wdata <= #1 10'b0;
    else if(clken)
	fb_wdata <= #1 fb_wdata;
    else if((stage==2'd2) && (!slot[0]))
	fb_wdata <= #1 fb_wdata_tmp;
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	mo_wr <= #1 1'b0;
    else if(clken)
	mo_wr <= #1 mo_wr;
    else if(stage == 2'b0)
	mo_wr <= #1 1'b0;
    else if(stage == 2'd2)
	mo_wr <= #1 1'b1;
    else if(stage == 2'd3)
	mo_wr <= #1 1'b0;
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	mo_addr <= #1 5'b0;
    else if(clken)
	mo_addr <= #1 mo_addr;
    else if((stage == 2'd0) || (stage == 2'd2))
	mo_addr <= #1 slot;
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	mo_wdata <= #1 10'b0;
    else if(stage==2'd2)
	mo_wdata <= #1 li_data;
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	li_addr <= #1 8'b0;
    else if(stage == 2'd0)
	li_addr <= #1 opout;
end


endmodule
